/**
 * echarts图表动画基类
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */


var zrUtil = require('zrender/tool/util');
var curveTool = require('zrender/tool/curve');
/**
     * 折线型动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function pointList(zr, oldShape, newShape, duration, easing) {
    var newPointList = newShape.style.pointList;
    var newPointListLen = newPointList.length;
    var oldPointList;
    if (!oldShape) {
        // add
        oldPointList = [];
        if (newShape._orient != 'vertical') {
            var y = newPointList[0][1];
            for (var i = 0; i < newPointListLen; i++) {
                oldPointList[i] = [
                    newPointList[i][0],
                    y
                ];
            }
        } else {
            var x = newPointList[0][0];
            for (var i = 0; i < newPointListLen; i++) {
                oldPointList[i] = [
                    x,
                    newPointList[i][1]
                ];
            }
        }
        if (newShape.type == 'half-smooth-polygon') {
            oldPointList[newPointListLen - 1] = zrUtil.clone(newPointList[newPointListLen - 1]);
            oldPointList[newPointListLen - 2] = zrUtil.clone(newPointList[newPointListLen - 2]);
        }
        oldShape = { style: { pointList: oldPointList } };
    }
    oldPointList = oldShape.style.pointList;
    var oldPointListLen = oldPointList.length;
    if (oldPointListLen == newPointListLen) {
        newShape.style.pointList = oldPointList;
    } else if (oldPointListLen < newPointListLen) {
        // 原来短，新的长，补全
        newShape.style.pointList = oldPointList.concat(newPointList.slice(oldPointListLen));
    } else {
        // 原来长，新的短，截断
        newShape.style.pointList = oldPointList.slice(0, newPointListLen);
    }
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, { pointList: newPointList }).during(function () {
        // Updating bezier points
        if (newShape.updateControlPoints) {
            newShape.updateControlPoints(newShape.style);
        }
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 复制样式
     * 
     * @inner
     * @param {Object} target 目标对象
     * @param {Object} source 源对象
     * @param {...string} props 复制的属性列表
     */
function cloneStyle(target, source) {
    var len = arguments.length;
    for (var i = 2; i < len; i++) {
        var prop = arguments[i];
        target.style[prop] = source.style[prop];
    }
}
/**
     * 方型动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function rectangle(zr, oldShape, newShape, duration, easing) {
    var newShapeStyle = newShape.style;
    if (!oldShape) {
        // add
        oldShape = {
            position: newShape.position,
            style: {
                x: newShapeStyle.x,
                y: newShape._orient == 'vertical' ? newShapeStyle.y + newShapeStyle.height : newShapeStyle.y,
                width: newShape._orient == 'vertical' ? newShapeStyle.width : 0,
                height: newShape._orient != 'vertical' ? newShapeStyle.height : 0
            }
        };
    }
    var newX = newShapeStyle.x;
    var newY = newShapeStyle.y;
    var newWidth = newShapeStyle.width;
    var newHeight = newShapeStyle.height;
    var newPosition = [
        newShape.position[0],
        newShape.position[1]
    ];
    cloneStyle(newShape, oldShape, 'x', 'y', 'width', 'height');
    newShape.position = oldShape.position;
    zr.addShape(newShape);
    if (newPosition[0] != oldShape.position[0] || newPosition[1] != oldShape.position[1]) {
        zr.animate(newShape.id, '').when(duration, { position: newPosition }).start(easing);
    }
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
        x: newX,
        y: newY,
        width: newWidth,
        height: newHeight
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 蜡烛动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function candle(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        // add
        var y = newShape.style.y;
        oldShape = {
            style: {
                y: [
                    y[0],
                    y[0],
                    y[0],
                    y[0]
                ]
            }
        };
    }
    var newY = newShape.style.y;
    newShape.style.y = oldShape.style.y;
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, { y: newY }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 环型动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function ring(zr, oldShape, newShape, duration, easing) {
    var x = newShape.style.x;
    var y = newShape.style.y;
    var r0 = newShape.style.r0;
    var r = newShape.style.r;
    newShape.__animating = true;
    if (newShape._animationAdd != 'r') {
        newShape.style.r0 = 0;
        newShape.style.r = 0;
        newShape.rotation = [
            Math.PI * 2,
            x,
            y
        ];
        zr.addShape(newShape);
        zr.animate(newShape.id, 'style').when(duration, {
            r0: r0,
            r: r
        }).done(function () {
            newShape.__animating = false;
        }).start(easing);
        zr.animate(newShape.id, '').when(duration, {
            rotation: [
                0,
                x,
                y
            ]
        }).start(easing);
    } else {
        newShape.style.r0 = newShape.style.r;
        zr.addShape(newShape);
        zr.animate(newShape.id, 'style').when(duration, { r0: r0 }).done(function () {
            newShape.__animating = false;
        }).start(easing);
    }
}
/**
     * 扇形动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function sector(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        // add
        if (newShape._animationAdd != 'r') {
            oldShape = {
                style: {
                    startAngle: newShape.style.startAngle,
                    endAngle: newShape.style.startAngle
                }
            };
        } else {
            oldShape = { style: { r0: newShape.style.r } };
        }
    }
    var startAngle = newShape.style.startAngle;
    var endAngle = newShape.style.endAngle;
    cloneStyle(newShape, oldShape, 'startAngle', 'endAngle');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
        startAngle: startAngle,
        endAngle: endAngle
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 文本动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function text(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        // add
        oldShape = {
            style: {
                x: newShape.style.textAlign == 'left' ? newShape.style.x + 100 : newShape.style.x - 100,
                y: newShape.style.y
            }
        };
    }
    var x = newShape.style.x;
    var y = newShape.style.y;
    cloneStyle(newShape, oldShape, 'x', 'y');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
        x: x,
        y: y
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 多边形动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function polygon(zr, oldShape, newShape, duration, easing) {
    var rect = require('zrender/shape/Polygon').prototype.getRect(newShape.style);
    var x = rect.x + rect.width / 2;
    var y = rect.y + rect.height / 2;
    newShape.scale = [
        0.1,
        0.1,
        x,
        y
    ];
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, '').when(duration, {
        scale: [
            1,
            1,
            x,
            y
        ]
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * 和弦动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function ribbon(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        // add
        oldShape = {
            style: {
                source0: 0,
                source1: newShape.style.source1 > 0 ? 360 : -360,
                target0: 0,
                target1: newShape.style.target1 > 0 ? 360 : -360
            }
        };
    }
    var source0 = newShape.style.source0;
    var source1 = newShape.style.source1;
    var target0 = newShape.style.target0;
    var target1 = newShape.style.target1;
    if (oldShape.style) {
        cloneStyle(newShape, oldShape, 'source0', 'source1', 'target0', 'target1');
    }
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
        source0: source0,
        source1: source1,
        target0: target0,
        target1: target1
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * gaugePointer动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function gaugePointer(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        // add
        oldShape = { style: { angle: newShape.style.startAngle } };
    }
    var angle = newShape.style.angle;
    newShape.style.angle = oldShape.style.angle;
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, { angle: angle }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * icon动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function icon(zr, oldShape, newShape, duration, easing, delay) {
    // 避免markPoint特效取值在动画帧上
    newShape.style._x = newShape.style.x;
    newShape.style._y = newShape.style.y;
    newShape.style._width = newShape.style.width;
    newShape.style._height = newShape.style.height;
    if (!oldShape) {
        // add
        var x = newShape._x || 0;
        var y = newShape._y || 0;
        newShape.scale = [
            0.01,
            0.01,
            x,
            y
        ];
        zr.addShape(newShape);
        newShape.__animating = true;
        zr.animate(newShape.id, '').delay(delay).when(duration, {
            scale: [
                1,
                1,
                x,
                y
            ]
        }).done(function () {
            newShape.__animating = false;
        }).start(easing || 'QuinticOut');
    } else {
        // mod
        rectangle(zr, oldShape, newShape, duration, easing);
    }
}
/**
     * line动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function line(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
        oldShape = {
            style: {
                xStart: newShape.style.xStart,
                yStart: newShape.style.yStart,
                xEnd: newShape.style.xStart,
                yEnd: newShape.style.yStart
            }
        };
    }
    var xStart = newShape.style.xStart;
    var xEnd = newShape.style.xEnd;
    var yStart = newShape.style.yStart;
    var yEnd = newShape.style.yEnd;
    cloneStyle(newShape, oldShape, 'xStart', 'xEnd', 'yStart', 'yEnd');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
        xStart: xStart,
        xEnd: xEnd,
        yStart: yStart,
        yEnd: yEnd
    }).done(function () {
        newShape.__animating = false;
    }).start(easing);
}
/**
     * markline动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
function markline(zr, oldShape, newShape, duration, easing) {
    easing = easing || 'QuinticOut';
    newShape.__animating = true;
    zr.addShape(newShape);
    var newShapeStyle = newShape.style;
    var animationDone = function () {
        newShape.__animating = false;
    };
    var x0 = newShapeStyle.xStart;
    var y0 = newShapeStyle.yStart;
    var x2 = newShapeStyle.xEnd;
    var y2 = newShapeStyle.yEnd;
    if (newShapeStyle.curveness > 0) {
        newShape.updatePoints(newShapeStyle);
        var obj = { p: 0 };
        var x1 = newShapeStyle.cpX1;
        var y1 = newShapeStyle.cpY1;
        var newXArr = [];
        var newYArr = [];
        var subdivide = curveTool.quadraticSubdivide;
        zr.animation.animate(obj).when(duration, { p: 1 }).during(function () {
            // Calculate subdivided curve
            subdivide(x0, x1, x2, obj.p, newXArr);
            subdivide(y0, y1, y2, obj.p, newYArr);
            newShapeStyle.cpX1 = newXArr[1];
            newShapeStyle.cpY1 = newYArr[1];
            newShapeStyle.xEnd = newXArr[2];
            newShapeStyle.yEnd = newYArr[2];
            zr.modShape(newShape);
        }).done(animationDone).start(easing);
    } else {
        zr.animate(newShape.id, 'style').when(0, {
            xEnd: x0,
            yEnd: y0
        }).when(duration, {
            xEnd: x2,
            yEnd: y2
        }).done(animationDone).start(easing);
    }
}
module.exports = {
    pointList: pointList,
    rectangle: rectangle,
    candle: candle,
    ring: ring,
    sector: sector,
    text: text,
    polygon: polygon,
    ribbon: ribbon,
    gaugePointer: gaugePointer,
    icon: icon,
    line: line,
    markline: markline
} || module.exports;;